/*
 * Swipe 1.0
 *
 * Brad Birdsall, Prime
 * Copyright 2011, Licensed GPL & MIT
 *
*/

; window.Swipe = function (element, options) {

    // return immediately if element doesn't exist
    if (!element) return null;

    var _this = this;

    // retreive options
    this.options = options || {};
    this.times=this.options.times||0;
    this.speed = this.options.speed || 300;
    this.callback = this.options.callback || function () { };
    this.delay = this.options.auto || 0;

    // reference dom elements
    this.container = element;
    this.element = this.container.children[0]; // the slide pane
    this.element.innerHTML += this.element.innerHTML;
    this.index = this.element.children.length / 2 - 1;
    // static css
    this.container.style.overflow = '';
    this.element.style.listStyle = 'none';
    this.element.style.margin = 0;
	this.toString=Object.prototype.toString;

    // trigger slider initialization
    this.setup();

    // begin auto slideshow
    this.begin();
	
	this.autoTime();
    // add event listeners
    if (this.element.addEventListener) {
        this.element.addEventListener('touchstart', this, false);
        this.element.addEventListener('touchmove', this, false);
        this.element.addEventListener('touchend', this, false);
        this.element.addEventListener('touchcancel', this, false);
        this.element.addEventListener('webkitTransitionEnd', this, false);
        this.element.addEventListener('msTransitionEnd', this, false);
        this.element.addEventListener('oTransitionEnd', this, false);
        this.element.addEventListener('transitionend', this, false);
        window.addEventListener('resize', this, false);
    }

};

Swipe.prototype = {

    setup: function () {

        // get and measure amt of slides
        this.slides = this.element.children;
        this.length = this.slides.length;
        
        // return immediately if their are less than two slides
        if (this.length < 2) return null;

        // determine width of each slide
        this.width = Math.ceil(("getBoundingClientRect" in this.container) ? this.container.getBoundingClientRect().width : this.container.offsetWidth);

        // Fix width for Android WebView (i.e. PhoneGap) 
        if (this.width === 0 && typeof window.getComputedStyle === 'function') {
            this.width = window.getComputedStyle(this.container, null).width.replace('px', '');
        }

        // return immediately if measurement fails
        if (!this.width) return null;

        // hide slider element but keep positioning during setup
        var origVisibility = this.container.style.visibility;
        this.container.style.visibility = 'hidden';

        // dynamic css
        this.element.style.width = Math.ceil(this.slides.length * this.width) + 'px';
        var index = this.slides.length;
        while (index--) {
            var el = this.slides[index];
            el.style.width = this.width + 'px';
            el.style.display = 'table-cell';
            el.style.verticalAlign = 'top';
        }

        // set start position and force translate to remove initial flickering
        this.slide(this.length/2, 0);

        // restore the visibility of the slider element
        this.container.style.visibility = origVisibility;

    },
	autoTime:function(){
		if(this.times>0){
			 var _this=this;
			this.autoTimeObj=setInterval(function(){				
				_this.next();
			},_this.times); 
		}
	},
    slide: function (index, duration) {

        var style = this.element.style;

        // fallback to default speed
        if (duration == undefined) {
            duration = this.speed;
        }

        // set duration speed (0 represents 1-to-1 scrolling)
        style.webkitTransitionDuration = style.MozTransitionDuration = style.msTransitionDuration = style.OTransitionDuration = style.transitionDuration = duration + 'ms';

        // translate to given index position
        style.MozTransform = style.webkitTransform = 'translate3d(' + -(index * this.width) + 'px,0,0)';
        style.msTransform = style.OTransform = 'translateX(' + -(index * this.width) + 'px)';
        var _this = this;
        
        if (index > this.length / 2) {
            index = this.index - this.length / 2+1;
            setTimeout(function() {
                _this.slide(index, 0);
             
                _this.callback(window.event, index, _this.slides[_this.index]);
            },duration);
        }else if (index == 0) {
            index = this.length / 2;
            setTimeout(function () {
                _this.slide(index, 0);
                var i = index;
                if (i >= this.length / 2) {
                    i = index - _this.length / 2; 
                } 
                _this.callback(window.event, i, _this.slides[_this.index]);
            }, duration);
        }
		
		setTimeout(function(){
			 if(!_this.autoTimeObj){_this.autoTime();}
		},duration);
        // set new index to allow for expression arguments
        this.index = index;

    },

    getPos: function () {

        // return current index position
        return this.index;

    },

    prev: function (delay) {

        // cancel next scheduled automatic transition, if any
        this.delay = delay || 0;
        clearTimeout(this.interval); 
		if(typeof delay =="object"){
			if(this.autoTimeObj){ 
				window.clearInterval(this.autoTimeObj);
				this.autoTimeObj=null;
			}
		}
        if (this.index) this.slide(this.index - 1, this.speed); // if not at first slide
        else this.slide(this.length - 1, this.speed); //if first slide return to end

    },

    next: function (delay) { 
        // cancel next scheduled automatic transition, if any
        this.delay = delay || 0;
		
        clearTimeout(this.interval);
		 
		if(typeof delay =="object"){
			if(this.autoTimeObj){ 
				window.clearInterval(this.autoTimeObj);
				this.autoTimeObj=null;
			}
		}
        if (this.index < this.length - 1) this.slide(this.index + 1, this.speed); // if not last slide
        else this.slide(0, this.speed); //if last slide return to start

    },

    begin: function () {
 
        var _this = this;

        this.interval = (this.delay)
          ? setTimeout(function () {
              _this.next(_this.delay);
          }, this.delay)
          : 0;

    },

    stop: function () {
        this.delay = 0;
        clearTimeout(this.interval);
    },

    resume: function () {
        this.delay = this.options.auto || 0;
        this.begin();
    },

    handleEvent: function (e) {
        switch (e.type) {
            case 'touchstart': this.onTouchStart(e); break;
            case 'touchmove': this.onTouchMove(e); break;
            case 'touchcancel':
            case 'touchend': this.onTouchEnd(e); break;
            case 'webkitTransitionEnd':
            case 'msTransitionEnd':
            case 'oTransitionEnd':
            case 'transitionend': this.transitionEnd(e); break;
            case 'resize': this.setup(); break;
        }
    },

    transitionEnd: function (e) {
 
       // if (this.delay) this.begin();
        var i = this.index;
        var ii =parseInt(this.length / 2);
        if (this.index >= ii) {
            i -=ii;
        }
        this.callback(e, i, this.slides[this.index]);
    },

    onTouchStart: function (e) {

        this.start = {

            // get touch coordinates for delta calculations in onTouchMove
            pageX: e.touches[0].pageX,
            pageY: e.touches[0].pageY,

            // set initial timestamp of touch sequence
            time: Number(new Date())

        };

        // used for testing first onTouchMove event
        this.isScrolling = undefined;

        // reset deltaX
        this.deltaX = 0;

        // set transition time to 0 for 1-to-1 touch movement
        this.element.style.MozTransitionDuration = this.element.style.webkitTransitionDuration = 0;

        e.stopPropagation();
    },

    onTouchMove: function (e) {

        // ensure swiping with one touch and not pinching
        if (e.touches.length > 1 || e.scale && e.scale !== 1) return;

        this.deltaX = e.touches[0].pageX - this.start.pageX;

        // determine if scrolling test has run - one time test
        if (typeof this.isScrolling == 'undefined') {
            this.isScrolling = !!(this.isScrolling || Math.abs(this.deltaX) < Math.abs(e.touches[0].pageY - this.start.pageY));
        }
		if(this.autoTimeObj){ 
			window.clearInterval(this.autoTimeObj);
			this.autoTimeObj=null;
		}
       /* // if user is not trying to scroll vertically
        if (!this.isScrolling) {

            // prevent native scrolling 
            e.preventDefault();

            // cancel slideshow
            clearTimeout(this.interval);

            // increase resistance if first or last slide
            this.deltaX =
              this.deltaX /
                ((!this.index && this.deltaX > 0               // if first slide and sliding left
                  || this.index == this.length - 1              // or if last slide and sliding right
                  && this.deltaX < 0                            // and if sliding at all
                ) ?
                (Math.abs(this.deltaX) / this.width + 1)      // determine resistance level
                : 1);                                          // no resistance if false
		 
            // translate immediately 1-to-1
            this.element.style.MozTransform = this.element.style.webkitTransform = 'translate3d(' + (this.deltaX - this.index * this.width) + 'px,0,0)';

            e.stopPropagation();
        }*/
		if(!this.isScrolling){
			e.preventDefault();
			}

    },

    onTouchEnd: function (e) {

        // determine if slide attempt triggers next/prev slide
        var isValidSlide =
              Number(new Date()) - this.start.time < 250      // if slide duration is less than 250ms
              && Math.abs(this.deltaX) > 20                   // and if slide amt is greater than 20px
              || Math.abs(this.deltaX) > this.width / 2,        // or if slide amt is greater than half the width

        // determine if slide attempt is past start and end
            isPastBounds =
              !this.index && this.deltaX > 0                          // if first slide and slide amt is greater than 0
              || this.index == this.length - 1 && this.deltaX < 0;    // or if last slide and slide amt is less than 0

        // if not scrolling vertically
        if (!this.isScrolling) {

            // call slide function with slide end value based on isValidSlide and isPastBounds tests
            this.slide(this.index + (isValidSlide && !isPastBounds ? (this.deltaX < 0 ? 1 : -1) : 0), this.speed);

        }else{
			var _this=this;
			setTimeout(function(){
				 if(!_this.autoTimeObj){_this.autoTime();}
			},duration);
		}

        e.stopPropagation();
    }

};
